use crate::lexer::{Lexer, SourcePosition, Token};
#[derive(Debug, Clone)]
pub(crate) enum TreeNode {
    Var(String), // 变量节点, 包含变量名
    // 包含整数常量的节点,
    Cst(isize),
    Add(BoxNode, BoxNode), // 加法节点, 包含两个子节点

    Sub(BoxNode, BoxNode), // 减法节点, 包含两个子节点

    Lt(BoxNode, BoxNode), // 小于节点, 包含两个子节点

    /// 赋值 语句。 请注意，第一个参数必须是 'Var（_）'。
    Set(BoxNode, BoxNode),

    ///if 没有else的部分
    If1(BoxNode, BoxNode),

    /// 带有 'else' 部分的 'if' 语句。
    If2(BoxNode, BoxNode, BoxNode),

    /// 带有 test 和 body 的 'while' 语句
    While(BoxNode, BoxNode),

    ///带有 body 和 test 的 'do-while' 语句
    Do(BoxNode, BoxNode),
    ///null 语句，以方便编译器
    Empty,
    /// 序列节点，它将两个（或多个）语句连接在一起
    Seq(BoxNode, BoxNode),
    /// expression 语句
    Expr(BoxNode),
    Prog(BoxNode), // 程序节点，包含一个语句子节点
}
pub type BoxNode = Box<TreeNode>;

struct Parser<'a> {
    lexer: Lexer<'a>,         // 词法分析器
    position: SourcePosition, // 当前位置
    lookahead: Token,         //  存储下一个要解析的词法单元
}

impl<'a> Parser<'a> {
    pub(crate) fn program_node(&mut self) -> TreeNode {
        let statement = self.statement_node();
        if !matches!(self.lookahead, Token::Eoi) {
            self.lexer
                .syntax_error( self.position , "Unexpected token after end of input",);
        }
        TreeNode::Prog(Box::new(statement))
    }
    pub fn term(&mut self) -> TreeNode {
        match &mut  self.lookahead {
            Token::Int(n) => {
                let name = n.to_owned(); // 克隆 `n` 以获取所有权
                self.next_token();
                TreeNode::Cst(name) //常通过克隆从借用的数据创建拥有的数据。
            }
            Token::Id(s) => { 
                let name = s.to_owned(); // 克隆 `s` 以获取所有权
                self.next_token();
                TreeNode::Var( name )
            }
            _ => {
                self.lexer
                    .syntax_error(self.position, "Expected integer or identifier");
                self.paren_expr()
            }
        }
    }
    pub fn paren_expr(&mut self) -> TreeNode {
        if !matches!(self.lookahead, Token::Lpar) {
            self.lexer.syntax_error(self.position, "`(' expected");
        }
        self.next_token();
        let x = self.expression_node();
        if !matches!(self.lookahead, Token::Rpar) {
            self.lexer.syntax_error(self.position, "`)' expected");
        }
        self.next_token();

        x
    }
    pub fn expression_node(&mut self) -> TreeNode {
        let mut t = self.term(); // 解析第一个因子
        loop {
            match self.lookahead {
                Token::Plus => {
                    self.next_token();
                    t = TreeNode::Add(Box::new(t), Box::new(self.term()));
                }
                Token::Minus => {
                    self.next_token();
                    t = TreeNode::Sub(Box::new(t), Box::new(self.term()));
                }
                _ => return t,
            }
        }
    }
    pub fn condition_expr(&mut self) -> TreeNode {
        let mut left = self.expression_node();
        if matches!(self.lookahead, Token::Less) {
            self.next_token();
            TreeNode::Lt(Box::new(left), Box::new(self.expression_node()))
        } else {
            left
        }
    }
    pub fn statement_node(&mut self) -> TreeNode {
        match self.lookahead {
            Token::IfSym => {
                self.next_token(); // 跳过 'if' 关键字
                let condition = self.condition_expr();
                let then_node = self.statement_node();

                if matches!(self.lookahead, Token::ElseSym) {
                    self.next_token();
                    TreeNode::If2(
                        Box::new(condition),
                        Box::new(then_node),
                        Box::new(self.statement_node()),
                    )
                } else {
                    TreeNode::If1(Box::new(condition), Box::new(then_node))
                }
            }
            Token::WhileSym => {
                self.next_token(); // 跳过 'while' 关键字
                let condition = self.paren_expr();
                let body = self.statement_node();
                TreeNode::While(Box::new(condition), Box::new(body))
            }
            Token::DoSym => {
                self.next_token(); // 跳过 'do' 关键字
                let body = self.statement_node();
                if !matches!(self.lookahead, Token::WhileSym) {
                    self.lexer.syntax_error(self.position, "expected 'while'");
                }
                self.next_token(); // 跳过 'while' 关键字
                let condition = self.condition_expr();
                if !matches!(self.lookahead, Token::Semi) {
                    self.lexer.syntax_error(self.position, "expected `;'");
                }
                self.next_token(); // 跳过 ';' 关键字
                TreeNode::Do(Box::new(body), Box::new(condition))
            }
            Token::Semi => {
                self.next_token();
                TreeNode::Empty
            }
            // statement 中文是语句
            Token::Lbra => {
                self.next_token();
                let mut node  = self.statement_node();
                while matches!(self.lookahead, Token::Rbra) {
                    node = TreeNode::Seq(Box::new(node), Box::new(self.statement_node()));
                }
                self.next_token();
                node 
            }
            _ => {
                let x = self.expression_node();
                if !matches!(self.lookahead, Token::Semi) {
                    self.lexer.syntax_error(self.position, "expected `;'");
                }
                self.next_token();
                TreeNode::Expr(Box::new(x)) // 表达式语句
            }
        }
    }
}

impl<'a> Parser<'a> {
    fn new(input: &'a str) -> Self {
        let mut parser = Parser {
            lexer: Lexer::new(input),
            position: SourcePosition::default(),
            lookahead: Token::new(),
        };
        parser.next_token();
        parser
    }

    fn next_token(&mut self) {
        (self.position, self.lookahead) = self.lexer.get_current_token();
    }
}
// 'static 具有全局的生命周期 , 一般不建议使用
#[must_use]
pub(crate) fn parse(str: &str) -> TreeNode {
    Parser::new(str).program_node()
}
